#pragma once
#include<vector>
#include<queue>
#include<string>
#include<memory>
#include<functional>
#include<unistd.h>
#include<pthread.h>
#include"Task.hpp"
#include"Thread.hpp"
#include"BlockingQueue.hpp"

namespace wbj
{
#define THREAD_NUM 10

    template<class T>
    class ThreadPool
    {
        using func_t=std::function<void(T&)>;
    public:
        ThreadPool(func_t func,int num=THREAD_NUM)
        :_num(num),_func(func)
        {}
        void init()
        {
            for(int i=0;i<_nums;i++)
            {

                _threads.push_back(Thread(i,threadRoutine,this));
            }
        }
        void start()
        {
            for(auto& t:_threads)
            {
                t.run();
            }
        }
        static void threadRoutine(void* args)
        {
            //避免等待线程，直接剥离
            pthread_detach(pthread_self());
            //线程任务是取出任务队列的任务并执行
            auto ptr=static_cast<ThreadPool<T>*>(args);
            while(true)
            {
                T task=ptr->popTask();

                task();
                ptr->callBack(task);
            }
        }

        void pushTask(const T& task)
        {
            _blockqueue.Push(task);
        }
        ~ThreadPool()
        {
            for(auto& t:_threads)
            {
                t.join();
            }
        }
    protected:
        func_t callBack(T& task)
        {
            _func(task);
        }
        T popTask()
        {
            T task;
            _blockqueue.Pop(&task);
            return task;
        }
    private:
        std::vector<Thread> _threads;
        int _num;
        BlockQueue<T> _blockqueue;
        func_t _func;
    };
}